#include "BinarySerializer.h"
#include <string.h>

CBinarySerializer::CBinarySerializer(TVector<uint8_t> &InBinary)
    : Binary(InBinary)
{
}

CBinarySerializer &CBinarySerializer::operator<<(const uint8_t &Value)
{
    Binary.Add(Value);
    return *this;
}

CBinarySerializer &CBinarySerializer::operator<<(const uint16_t &Value)
{
    Binary.Add(Value & 0xFF);
    Binary.Add((Value >> 8) & 0xFF);
    return *this;
}

CBinarySerializer &CBinarySerializer::operator<<(const uint32_t &Value)
{
    Binary.Add(Value & 0xFF);
    Binary.Add((Value >> 8) & 0xFF);
    Binary.Add((Value >> 16) & 0xFF);
    Binary.Add((Value >> 24) & 0xFF);
    return *this;
}

CBinarySerializer &CBinarySerializer::operator<<(const uint64_t &Value)
{
    Binary.Add(Value & 0xFF);
    Binary.Add((Value >> 8) & 0xFF);
    Binary.Add((Value >> 16) & 0xFF);
    Binary.Add((Value >> 24) & 0xFF);
    Binary.Add((Value >> 32) & 0xFF);
    Binary.Add((Value >> 40) & 0xFF);
    Binary.Add((Value >> 48) & 0xFF);
    Binary.Add((Value >> 56) & 0xFF);
    return *this;

}

CBinarySerializer &CBinarySerializer::operator<<(const CString &Value)
{
    *this << (uint32_t)Value.GetLength();

    Binary.Resize(Binary.Num() + Value.GetLength() * sizeof(char32_t) );

    memcpy((Binary.Data()+ (Binary.Num() - Value.GetLength() * sizeof(char32_t)))
        , Value.GetData()
        , Value.GetLength() * sizeof(char32_t));

    return *this;
}

void CBinarySerializer::Append(const void *Data, uint64_t Size)
{
    Binary.Resize(Binary.Num() + Size);

    memcpy((Binary.Data() + Binary.Num() - Size), Data, Size);

    return;
}

CBinaryDeserializer::CBinaryDeserializer(const TVector<uint8_t> &InBinary,uint64_t InOffset)
    : Binary(InBinary)
    , Offset(InOffset)
{
}

CBinaryDeserializer &CBinaryDeserializer::operator>>(uint8_t &Value)
{
    Value = Binary[Offset];
    Offset++;
    return *this;
}

CBinaryDeserializer &CBinaryDeserializer::operator>>(uint16_t &Value)
{
    Value = Binary[Offset];
    Offset++;
    Value |= Binary[Offset] << 8;
    Offset++;
    return *this;
}

CBinaryDeserializer &CBinaryDeserializer::operator>>(uint32_t &Value)
{
    Value = Binary[Offset];
    Offset++;
    Value |= (uint32_t)Binary[Offset] << 8;
    Offset++;
    Value |= (uint32_t)Binary[Offset] << 16;
    Offset++;
    Value |= (uint32_t)Binary[Offset] << 24;
    Offset++;
    return *this;
}

CBinaryDeserializer &CBinaryDeserializer::operator>>(uint64_t &Value)
{
    Value = Binary[Offset];
    Offset++;
    Value |= (uint64_t)Binary[Offset] << 8;
    Offset++;
    Value |= (uint64_t)Binary[Offset] << 16;
    Offset++;
    Value |= (uint64_t)Binary[Offset] << 24;
    Offset++;
    Value |= (uint64_t)Binary[Offset] << 32;
    Offset++;
    Value |= (uint64_t)Binary[Offset] << 40;
    Offset++;
    Value |= (uint64_t)Binary[Offset] << 48;
    Offset++;
    Value |= (uint64_t)Binary[Offset] << 56;
    Offset++;
    return *this;
}

CBinaryDeserializer &CBinaryDeserializer::operator>>(CString &Value)
{
    uint32_t Length = 0;
    *this >> Length;

    Value.Resize(Length);

    memcpy(
         (void*)Value.GetData()
        ,(void *)(Binary.Data()+ Offset)
        , Length * sizeof(char32_t));

    Offset += Length * sizeof(char32_t);
    return *this;
}

void * CBinaryDeserializer::TakeOut(uint64_t InSize)
{
    void *Data = (void *)(Binary.Data() + Offset);
    Offset += InSize;
    return  Data;
}
